#pragma once

#include <QObject>
#include <QString>
#include <QList>
#include <QSet>
#include <memory>
#include "kernel/domain/map_types.h"
#include "kernel/agv/agv_entity.h"
#include "kernel/interfaces/ILogger.h"
#include "application/map/area/area.h"

namespace application {
namespace charge {

/**
 * @brief 充电点类
 * @details 管理充电站的占用状态和预占用
 */
class ChargePoint : public QObject {
    Q_OBJECT

public:
    explicit ChargePoint(const QString& pointId, int floor, const kernel::Position& position,
                         std::shared_ptr<kernel::ILogger> logger = nullptr, QObject* parent = nullptr);
    ~ChargePoint() = default;

    // 基本信息
    QString getPointId() const { return m_pointId; }
    int getFloor() const { return m_floor; }
    kernel::Position getPosition() const { return m_position; }
    QString getStationPoint() const { return m_stationPoint; }
    QString getActionPoint() const { return m_actionPoint; }
    QString getAreaId() const { return m_areaId; }
    bool supportsAgvType(kernel::agv::AgvType type) const;

    // 占用管理
    bool isOccupied() const { return m_isOccupied; }
    int getCurrentOccupyingAgvId() const { return m_currentOccupyingAgvId; }
    bool occupy(int agvId);
    bool releaseOccupation();

    // 预占用管理
    bool isPreOccupied() const { return m_preOccupyingAgvId != -1; }
    int getPreOccupyingAgvId() const { return m_preOccupyingAgvId; }
    bool preOccupy(int agvId);
    bool releasePreOccupation(int agvId);

    // 关联区域
    void setArea(std::shared_ptr<area::Area> area);
    std::shared_ptr<area::Area> getArea() const { return m_area; }

    // 扩展属性
    void setStationPoint(const QString& stationPoint);
    void setAllowedVehicles(const QList<int>& allowedVehicles);
    void setBlockedVehicles(const QList<int>& blockedVehicles);
    void setActionPoint(const QString& actionPoint);
    void setSupportedAgvTypes(const QList<QString>& types);
    bool isVehicleAllowed(int agvId) const;
    const QSet<int>& allowedVehicles() const { return m_allowedVehicles; }

signals:
    void occupationChanged(bool occupied, int agvId);
    void preOccupationChanged(bool preOccupied, int agvId);

private slots:
    void onAreaEntered(int agvId, const QString& areaId);
    void onAreaExited(int agvId, const QString& areaId);

private:
    QString m_pointId;
    int m_floor;
    kernel::Position m_position;
    QString m_stationPoint;
    QString m_actionPoint;
    QString m_areaId;

    bool m_isOccupied = false;
    int m_currentOccupyingAgvId = -1;
    int m_preOccupyingAgvId = -1;

    std::shared_ptr<area::Area> m_area;
    std::shared_ptr<kernel::ILogger> m_logger;
    QSet<int> m_allowedVehicles;
    QSet<int> m_blockedVehicles;
    QSet<kernel::agv::AgvType> m_supportedAgvTypes;
};

} // namespace charge
} // namespace application
